﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace YJKRevitBase.ObjectPersistentSuit
{
	internal static class AssemblyUtility
	{
		internal static List<Assembly> GetAllAssembly(bool ifReCalculate = false)
		{
			if (ifReCalculate)
			{
				AssemblyUtility.m_lstAssemblyCatch = null;
			}
			if (AssemblyUtility.m_lstAssemblyCatch != null)
			{
				return AssemblyUtility.m_lstAssemblyCatch;
			}
			List<Assembly> list = new List<Assembly>();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			DirectoryInfo directory = new FileInfo(executingAssembly.Location).Directory;
			Assembly assembly = null;
			list.Add(executingAssembly);
			foreach (AssemblyName assemblyRef in executingAssembly.GetReferencedAssemblies())
			{
				assembly = null;
				try
				{
					assembly = Assembly.Load(assemblyRef);
				}
				catch (Exception)
				{
					assembly = null;
				}
				if (null != assembly)
				{
					list.Add(assembly);
				}
			}
			foreach (FileInfo fileInfo in directory.GetFiles())
			{
				assembly = null;
				try
				{
					if (AssemblyUtility.m_useFilterDelegate == null || !AssemblyUtility.m_useFilterDelegate(fileInfo))
					{
						assembly = Assembly.LoadFrom(fileInfo.FullName);
					}
				}
				catch (Exception)
				{
					assembly = null;
				}
				if (null != assembly && !list.Contains(assembly))
				{
					list.Add(assembly);
				}
			}
			AssemblyUtility.m_lstAssemblyCatch = list;
			return list;
		}

		internal static void GetAllInnerTypes(Type input, ref List<Type> lstTypes, ref Dictionary<string, Type> useDic)
		{
			if (null == input || lstTypes.Contains(input))
			{
				return;
			}
			string key = input.Assembly.FullName + input.FullName;
			if (useDic.ContainsKey(key))
			{
				return;
			}
			lstTypes.Add(input);
			useDic.Add(key, input);
			if (input.HasElementType)
			{
				AssemblyUtility.GetAllInnerTypes(input.GetElementType(), ref lstTypes, ref useDic);
			}
			Type[] genericArguments = input.GetGenericArguments();
			for (int i = 0; i < genericArguments.Length; i++)
			{
				AssemblyUtility.GetAllInnerTypes(genericArguments[i], ref lstTypes, ref useDic);
			}
			foreach (FieldInfo fieldInfo in input.GetRuntimeFields())
			{
				AssemblyUtility.GetAllInnerTypes(fieldInfo.FieldType, ref lstTypes, ref useDic);
			}
			if (null != input.BaseType)
			{
				AssemblyUtility.GetAllInnerTypes(input.BaseType, ref lstTypes, ref useDic);
			}
			lstTypes = lstTypes.Distinct<Type>().ToList<Type>();
		}

		internal static Type TryGetType(string typeName, Assembly oneAssembly)
		{
			Type result;
			try
			{
				result = oneAssembly.GetType(typeName);
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		internal static AssemblyFileFilterDelegate m_useFilterDelegate;

		private static List<Assembly> m_lstAssemblyCatch;
	}
}
